#pragma once

#include "sync_queue.h"

namespace cppdt {

    class ThreadPool;

    class IThreadTask {
    public:
        virtual ~IThreadTask() {}
        virtual void OnThread(const ThreadPool& sender, void* param) = 0;
    };

    class ThreadPool {
        struct ThreadInfo {
            std::thread* mThread;
            bool mEnable;

            ThreadInfo(std::thread* thread)
                : mThread(thread), mEnable(true) {}
        };

        struct ThreadData {
            IThreadTask* mTask;
            void* mParam;

            ThreadData(IThreadTask* task = nullptr, void* param = nullptr)
                : mTask(task), mParam(param) {}
        };

    public:
        ThreadPool();
        virtual ~ThreadPool();
        void Init(size_t minThreadNum, size_t maxThreadNum);
        void Join();
        void Execute(IThreadTask* task, void* param);

    private:
        ThreadPool(const ThreadPool&);
        ThreadPool& operator =(const ThreadPool&);
        virtual void OnThread();
        void AddThread();

    protected:
        size_t mMinNum;
        size_t mMaxNum;
        std::mutex mMutex;
        std::vector<ThreadInfo> mThreads;
        SyncQueue<ThreadData> mTasks;
    };

}
